package com.gitee.kenewstar.migration.function;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gitee.kenewstar.migration.constants.Const;
import com.gitee.kenewstar.migration.constants.FunctionCode;
import com.gitee.kenewstar.migration.core.AbstractSyncFunction;
import com.gitee.kenewstar.migration.core.ContextParam;
import com.gitee.kenewstar.migration.entity.CommonResult;
import com.gitee.kenewstar.migration.entity.TemplateHeader;
import com.gitee.kenewstar.migration.entity.TemplateHeaderTl;
import com.gitee.kenewstar.migration.entity.TemplateLine;
import com.gitee.kenewstar.migration.entity.TemplateLineTl;
import com.gitee.kenewstar.migration.entity.TemplateTarget;
import com.gitee.kenewstar.migration.entity.TemplateTargetTl;
import com.gitee.kenewstar.migration.service.TemplateImportService;
import lombok.Builder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author kenewstar
 */
@Slf4j
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ImportFunction extends AbstractSyncFunction<TemplateHeader> {

    private final TemplateImportService templateImportService;

    @Override
    protected Class<TemplateHeader> parameterType() {
        return TemplateHeader.class;
    }

    @Override
    public List<CommonResult> execute(ContextParam contextParam, List<TemplateHeader> list) {
        final List<TemplateHeader> headerList = this.templateImportService.devSelectHeaderList(list);
        if (CollUtil.isEmpty(headerList)) {
            return Collections.emptyList();
        }
        final List<Long> headerIds = headerList.stream().map(TemplateHeader::getId).collect(Collectors.toList());

        QueryWrapper<TemplateHeaderTl> headerTlQueryWrapper = new QueryWrapper<>();
        headerTlQueryWrapper.in("id", headerIds);
        final List<TemplateHeaderTl> headerTls = this.templateImportService.devSelectHeaderTl(headerTlQueryWrapper);
        final Map<Long, List<TemplateHeaderTl>> headerTlsMap = headerTls.stream().collect(Collectors.groupingBy(TemplateHeaderTl::getId));

        QueryWrapper<TemplateTarget> targetQueryWrapper = new QueryWrapper<>();
        targetQueryWrapper.in("header_id", headerIds);
        final List<TemplateTarget> targetList = this.templateImportService.devSelectTarget(targetQueryWrapper);
        final Map<Long, List<TemplateTarget>> targetListMap = targetList.stream().collect(Collectors.groupingBy(TemplateTarget::getHeaderId));

        final List<Long> targetIds = targetList.stream().map(TemplateTarget::getId).collect(Collectors.toList());
        // 有sheet数据
        Map<Long, List<TemplateTargetTl>> targetTlsMap;
        if (CollUtil.isNotEmpty(targetIds)) {
            QueryWrapper<TemplateTargetTl> targetTlQueryWrapper = new QueryWrapper<>();
            targetTlQueryWrapper.in("id", targetIds);
            final List<TemplateTargetTl> targetTls = this.templateImportService.devSelectTargetTl(targetTlQueryWrapper);
            targetTlsMap = targetTls.stream().collect(Collectors.groupingBy(TemplateTargetTl::getId));
        } else {
            targetTlsMap = new HashMap<>(0);
        }

        Map<Long, List<TemplateLine>> lineListMap;
        List<TemplateLine> lineList;
        if (CollUtil.isNotEmpty(targetIds)) {
            QueryWrapper<TemplateLine> lineQueryWrapper = new QueryWrapper<>();
            lineQueryWrapper.in("target_id", targetIds);
            lineList = this.templateImportService.devSelectLine(lineQueryWrapper);
            lineListMap = lineList.stream().collect(Collectors.groupingBy(TemplateLine::getTargetId));
        } else {
            lineListMap = new HashMap<>(0);
            lineList = Collections.emptyList();
        }

        Map<Long, List<TemplateLineTl>> lineTlsMap;
        if (CollUtil.isNotEmpty(lineList)) {
            final List<Long> lineIds = lineList.stream().map(TemplateLine::getId).collect(Collectors.toList());
            QueryWrapper<TemplateLineTl> lineTlQueryWrapper = new QueryWrapper<>();
            lineTlQueryWrapper.in("id", lineIds);
            final List<TemplateLineTl> lineTls = this.templateImportService.devSelectLineTl(lineTlQueryWrapper);
            lineTlsMap = lineTls.stream().collect(Collectors.groupingBy(TemplateLineTl::getId));
        } else {
            lineTlsMap = new HashMap<>(0);
        }

        contextParam.importContext = Context.builder().build();
        contextParam.importContext.headerTlsMap = headerTlsMap;
        contextParam.importContext.targetListMap = targetListMap;
        contextParam.importContext.targetTlsMap = targetTlsMap;
        contextParam.importContext.lineListMap = lineListMap;
        contextParam.importContext.lineTlsMap = lineTlsMap;

        List<CommonResult> resultList = new ArrayList<>(headerList.size());
        headerList.forEach(header -> {
            try {
                contextParam.importContext.header = header;
                this.self().singleExecute(contextParam);
                resultList.add(CommonResult.create(true).setTemplateCode(header.getTemplateCode()));
            } catch (Exception e) {
                resultList.add(CommonResult.create(false).setTemplateCode(header.getTemplateCode()).setErrorMsg(e.getMessage()));
                e.printStackTrace();
            }

        });
        return resultList;
    }

    @Override
    public FunctionCode functionCode() {
        return FunctionCode.IMPORT;
    }

    @Override
    @DS(Const.UAT)
    @Transactional(rollbackFor = Exception.class)
    public void singleExecute(ContextParam contextParam) {
        TemplateHeader header = contextParam.importContext.header;
        Map<Long, List<TemplateHeaderTl>> headerTlsMap = contextParam.importContext.headerTlsMap;
        Map<Long, List<TemplateTarget>> targetListMap = contextParam.importContext.targetListMap;
        Map<Long, List<TemplateTargetTl>> targetTlsMap = contextParam.importContext.targetTlsMap;
        Map<Long, List<TemplateLine>> lineListMap = contextParam.importContext.lineListMap;
        Map<Long, List<TemplateLineTl>> lineTlsMap = contextParam.importContext.lineTlsMap;

        final Long devHeaderId = header.getId();
        header.setId(null);
        this.templateImportService.uatInsertHeader(header);

        // 模板头的多语言数据
        final List<TemplateHeaderTl> headerTls1 = headerTlsMap.get(devHeaderId);
        headerTls1.forEach(v -> v.setId(header.getId()));
        this.templateImportService.uatInsertHeaderTl(headerTls1);

        // 模板sheet数据
        final List<TemplateTarget> targets = targetListMap.get(devHeaderId);
        if (CollUtil.isEmpty(targets)) {
            return;
        }
        targets.forEach(v -> v.setDevId(v.getId()));
        targets.forEach(v -> v.setId(null));
        targets.forEach(v -> v.setHeaderId(header.getId()));
        this.templateImportService.uatInsertTarget(targets);

        // 模板sheet多语言数据
        List<TemplateTargetTl> targetTlList = new ArrayList<>(10);
        for (TemplateTarget target : targets) {
            final List<TemplateTargetTl> targetTls = targetTlsMap.get(target.getDevId());
            targetTls.forEach(v -> v.setId(target.getId()));
            targetTlList.addAll(targetTls);
        }
        this.templateImportService.uatInsertTargetTl(targetTlList);


        List<TemplateLine> line2List = new ArrayList<>(10);
        for (TemplateTarget target : targets) {
            final List<TemplateLine> lines = lineListMap.get(target.getDevId());
            if (CollUtil.isEmpty(lines)) {
                continue;
            }
            lines.forEach(v -> v.setTargetId(target.getId()));
            lines.forEach(v -> v.setDevId(v.getId()));
            lines.forEach(v -> v.setId(null));
            line2List.addAll(lines);

        }
        if (CollUtil.isEmpty(line2List)) {
            return;
        }
        this.templateImportService.uatInsertLine(line2List);
        // 模板列多语言
        List<TemplateLineTl> lineTlList = new ArrayList<>(10);
        for (TemplateLine templateLine : line2List) {
            final List<TemplateLineTl> lineTls = lineTlsMap.get(templateLine.getDevId());
            if (CollUtil.isEmpty(lineTls)) {
                continue;
            }
            lineTls.forEach(v -> v.setId(templateLine.getId()));
            lineTlList.addAll(lineTls);
        }
        if (CollUtil.isNotEmpty(lineTlList)) {
            this.templateImportService.uatInsertLineTl(lineTlList);
        }
    }

    @Builder
    @SuppressWarnings("all")
    public static class Context {
        public TemplateHeader header;
        public Map<Long, List<TemplateHeaderTl>> headerTlsMap;
        public Map<Long, List<TemplateTarget>> targetListMap;
        public Map<Long, List<TemplateTargetTl>> targetTlsMap;
        public Map<Long, List<TemplateLine>> lineListMap;
        public Map<Long, List<TemplateLineTl>> lineTlsMap;

    }

}
